#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
API测试运行器
统一执行所有API测试模块并生成综合报告
@api-version: 1.0.0
"""

import os
import sys
import json
import subprocess
from datetime import datetime
import time

# 添加项目根目录到Python路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

class APITestRunner:
    """API测试运行器"""
    
    def __init__(self):
        self.test_dir = os.path.join(os.path.dirname(__file__), 'api')
        self.results = []
        self.start_time = None
        self.end_time = None
        
    def discover_test_modules(self):
        """发现所有测试模块"""
        test_modules = []
        
        if not os.path.exists(self.test_dir):
            print(f"[ERROR] 测试目录不存在: {self.test_dir}")
            return test_modules
        
        for filename in os.listdir(self.test_dir):
            if filename.startswith('test_') and filename.endswith('_api.py'):
                module_path = os.path.join(self.test_dir, filename)
                test_modules.append({
                    'name': filename[:-3],  # 去掉.py后缀
                    'path': module_path,
                    'display_name': self._get_display_name(filename)
                })
        
        return sorted(test_modules, key=lambda x: x['name'])
    
    def _get_display_name(self, filename):
        """获取测试模块的显示名称"""
        name_map = {
            'test_auth_api.py': '认证API测试',
            'test_user_api.py': '用户管理API测试',
            'test_share189_api.py': '189云盘分享API测试',
            'test_virtual_disk_api.py': '虚拟网盘API测试'
        }
        return name_map.get(filename, filename[:-3])
    
    def run_single_test(self, module):
        """运行单个测试模块"""
        print(f"\n{'='*60}")
        print(f"开始运行: {module['display_name']}")
        print(f"{'='*60}")
        
        start_time = time.time()
        
        try:
            # 使用subprocess运行测试模块
            result = subprocess.run(
                [sys.executable, module['path']],
                capture_output=True,
                text=True,
                timeout=300,  # 5分钟超时
                cwd=os.path.dirname(os.path.dirname(os.path.dirname(module['path'])))  # 项目根目录
            )
            
            end_time = time.time()
            duration = end_time - start_time
            
            success = result.returncode == 0
            
            test_result = {
                'module': module['name'],
                'display_name': module['display_name'],
                'success': success,
                'duration': duration,
                'stdout': result.stdout,
                'stderr': result.stderr,
                'return_code': result.returncode,
                'timestamp': datetime.now().isoformat()
            }
            
            self.results.append(test_result)
            
            # 输出结果
            if success:
                print(f"[PASS] {module['display_name']} 测试完成 (耗时: {duration:.2f}秒)")
            else:
                print(f"[FAIL] {module['display_name']} 测试失败 (耗时: {duration:.2f}秒)")
                if result.stderr:
                    print(f"错误信息: {result.stderr}")
            
            # 输出测试输出（如果有的话）
            if result.stdout:
                print(result.stdout)
            
            return success
            
        except subprocess.TimeoutExpired:
            print(f"[TIMEOUT] {module['display_name']} 测试超时")
            test_result = {
                'module': module['name'],
                'display_name': module['display_name'],
                'success': False,
                'duration': 300,
                'stdout': '',
                'stderr': '测试超时',
                'return_code': -1,
                'timestamp': datetime.now().isoformat()
            }
            self.results.append(test_result)
            return False
            
        except Exception as e:
            print(f"[ERROR] {module['display_name']} 运行异常: {str(e)}")
            test_result = {
                'module': module['name'],
                'display_name': module['display_name'],
                'success': False,
                'duration': 0,
                'stdout': '',
                'stderr': str(e),
                'return_code': -1,
                'timestamp': datetime.now().isoformat()
            }
            self.results.append(test_result)
            return False
    
    def run_all_tests(self):
        """运行所有测试"""
        self.start_time = datetime.now()
        
        print("[START] API测试套件开始运行")
        print(f"开始时间: {self.start_time.strftime('%Y-%m-%d %H:%M:%S')}")
        
        # 发现测试模块
        test_modules = self.discover_test_modules()
        
        if not test_modules:
            print("[ERROR] 未发现任何测试模块")
            return False
        
        print(f"\n发现 {len(test_modules)} 个测试模块:")
        for module in test_modules:
            print(f"  - {module['display_name']}")
        
        # 运行所有测试
        success_count = 0
        for module in test_modules:
            if self.run_single_test(module):
                success_count += 1
        
        self.end_time = datetime.now()
        
        # 生成总结报告
        self.generate_summary_report(len(test_modules), success_count)
        
        return success_count == len(test_modules)
    
    def generate_summary_report(self, total_modules, success_count):
        """生成总结报告"""
        duration = (self.end_time - self.start_time).total_seconds()
        
        print(f"\n{'='*80}")
        print("[COMPLETE] API测试套件执行完成")
        print(f"{'='*80}")
        print(f"开始时间: {self.start_time.strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"结束时间: {self.end_time.strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"总耗时: {duration:.2f}秒")
        print(f"\n测试模块统计:")
        print(f"  总数: {total_modules}")
        print(f"  成功: {success_count}")
        print(f"  失败: {total_modules - success_count}")
        print(f"  成功率: {(success_count/total_modules*100):.1f}%")
        
        # 详细结果
        print(f"\n详细结果:")
        for result in self.results:
            status = "[PASS]" if result['success'] else "[FAIL]"
            print(f"  {status} {result['display_name']} (耗时: {result['duration']:.2f}秒)")
            if not result['success'] and result['stderr']:
                print(f"      错误: {result['stderr'][:100]}..." if len(result['stderr']) > 100 else f"      错误: {result['stderr']}")
        
        # 保存详细报告
        self.save_detailed_report()
    
    def save_detailed_report(self):
        """保存详细测试报告"""
        report_data = {
            'summary': {
                'start_time': self.start_time.isoformat(),
                'end_time': self.end_time.isoformat(),
                'duration': (self.end_time - self.start_time).total_seconds(),
                'total_modules': len(self.results),
                'success_count': sum(1 for r in self.results if r['success']),
                'success_rate': sum(1 for r in self.results if r['success']) / len(self.results) * 100 if self.results else 0
            },
            'results': self.results,
            'environment': {
                'python_version': sys.version,
                'platform': sys.platform,
                'working_directory': os.getcwd()
            }
        }
        
        # 生成报告文件名
        timestamp = self.start_time.strftime('%Y%m%d_%H%M%S')
        report_file = f"api_test_report_{timestamp}.json"
        
        try:
            with open(report_file, 'w', encoding='utf-8') as f:
                json.dump(report_data, f, ensure_ascii=False, indent=2)
            
            print(f"\n[INFO] 详细测试报告已保存: {report_file}")
            
            # 同时生成简化的HTML报告
            self.generate_html_report(report_data, f"api_test_report_{timestamp}.html")
            
        except Exception as e:
            print(f"[ERROR] 保存测试报告失败: {str(e)}")
    
    def generate_html_report(self, report_data, filename):
        """生成HTML格式的测试报告"""
        try:
            html_content = f"""
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API测试报告</title>
    <style>
        body {{ font-family: 'Microsoft YaHei', Arial, sans-serif; margin: 20px; background-color: #f5f5f5; }}
        .container {{ max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }}
        .header {{ text-align: center; margin-bottom: 30px; }}
        .summary {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; }}
        .summary-card {{ background: #f8f9fa; padding: 20px; border-radius: 8px; text-align: center; }}
        .summary-card h3 {{ margin: 0 0 10px 0; color: #333; }}
        .summary-card .value {{ font-size: 2em; font-weight: bold; color: #007bff; }}
        .results {{ margin-top: 30px; }}
        .result-item {{ margin-bottom: 20px; padding: 15px; border-radius: 8px; border-left: 4px solid #ddd; }}
        .result-item.success {{ background: #d4edda; border-left-color: #28a745; }}
        .result-item.failure {{ background: #f8d7da; border-left-color: #dc3545; }}
        .result-header {{ display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }}
        .result-title {{ font-weight: bold; font-size: 1.1em; }}
        .result-duration {{ color: #666; font-size: 0.9em; }}
        .result-error {{ background: #fff; padding: 10px; border-radius: 4px; font-family: monospace; font-size: 0.9em; color: #dc3545; margin-top: 10px; }}
        .timestamp {{ text-align: center; color: #666; margin-top: 30px; font-size: 0.9em; }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>API测试报告</h1>
            <p>生成时间: {report_data['summary']['start_time']}</p>
        </div>
        
        <div class="summary">
            <div class="summary-card">
                <h3>总测试数</h3>
                <div class="value">{report_data['summary']['total_modules']}</div>
            </div>
            <div class="summary-card">
                <h3>成功数</h3>
                <div class="value" style="color: #28a745;">{report_data['summary']['success_count']}</div>
            </div>
            <div class="summary-card">
                <h3>失败数</h3>
                <div class="value" style="color: #dc3545;">{report_data['summary']['total_modules'] - report_data['summary']['success_count']}</div>
            </div>
            <div class="summary-card">
                <h3>成功率</h3>
                <div class="value" style="color: {'#28a745' if report_data['summary']['success_rate'] >= 80 else '#ffc107' if report_data['summary']['success_rate'] >= 60 else '#dc3545'};">{report_data['summary']['success_rate']:.1f}%</div>
            </div>
            <div class="summary-card">
                <h3>总耗时</h3>
                <div class="value">{report_data['summary']['duration']:.1f}s</div>
            </div>
        </div>
        
        <div class="results">
            <h2>详细结果</h2>
"""
            
            for result in report_data['results']:
                status_class = 'success' if result['success'] else 'failure'
                status_icon = '[PASS]' if result['success'] else '[FAIL]'
                
                html_content += f"""
            <div class="result-item {status_class}">
                <div class="result-header">
                    <div class="result-title">{status_icon} {result['display_name']}</div>
                    <div class="result-duration">耗时: {result['duration']:.2f}秒</div>
                </div>
"""
                
                if not result['success'] and result['stderr']:
                    html_content += f"""
                <div class="result-error">
                    错误信息: {result['stderr'][:500]}{'...' if len(result['stderr']) > 500 else ''}
                </div>
"""
                
                html_content += "</div>\n"
            
            html_content += f"""
        </div>
        
        <div class="timestamp">
            <p>报告生成于: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
        </div>
    </div>
</body>
</html>
"""
            
            with open(filename, 'w', encoding='utf-8') as f:
                f.write(html_content)
            
            print(f"[INFO] HTML测试报告已保存: {filename}")
            
        except Exception as e:
            print(f"[ERROR] 生成HTML报告失败: {str(e)}")

def main():
    """主函数"""
    runner = APITestRunner()
    success = runner.run_all_tests()
    
    return 0 if success else 1

if __name__ == '__main__':
    exit(main())